home *** CD-ROM | disk | FTP | other *** search
/ AGA Toolkit '97 / The AGA Toolkit '97.iso / programming / c / make-3.75 / glob / glob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-07  |  16.3 KB  |  694 lines

  1. /* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
  2.  
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public License as
  5. published by the Free Software Foundation; either version 2 of the
  6. License, or (at your option) any later version.
  7.  
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11. Library General Public License for more details.
  12.  
  13. You should have received a copy of the GNU Library General Public
  14. License along with this library; see the file COPYING.LIB.  If
  15. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  16. Cambridge, MA 02139, USA.  */
  17.  
  18. /* AIX requires this to be the first thing in the file.  */
  19. #if defined (_AIX) && !defined (__GNUC__)
  20.  #pragma alloca
  21. #endif
  22.  
  23. #ifdef    HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26.  
  27. #include <errno.h>
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30.  
  31.  
  32. /* Comment out all this code if we are using the GNU C Library, and are not
  33.    actually compiling the library itself.  This code is part of the GNU C
  34.    Library, but also included in many other GNU distributions.  Compiling
  35.    and linking in this code is a waste when using the GNU C library
  36.    (especially if it is a shared library).  Rather than having every GNU
  37.    program understand `configure --with-gnu-libc' and omit the object files,
  38.    it is simpler to just do this in the source for each such file.  */
  39.  
  40. #if defined (_LIBC) || !defined (__GNU_LIBRARY__)
  41.  
  42.  
  43. #ifdef    STDC_HEADERS
  44. #include <stddef.h>
  45. #endif
  46.  
  47. #ifdef    HAVE_UNISTD_H
  48. #include <unistd.h>
  49. #ifndef POSIX
  50. #ifdef    _POSIX_VERSION
  51. #define    POSIX
  52. #endif
  53. #endif
  54. #endif
  55.  
  56. #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
  57. extern int errno;
  58. #endif
  59.  
  60. #ifndef    NULL
  61. #define    NULL    0
  62. #endif
  63.  
  64.  
  65. #if    defined (POSIX) || defined (HAVE_DIRENT_H) || defined (__GNU_LIBRARY__)
  66. #include <dirent.h>
  67. #ifndef    __GNU_LIBRARY__
  68. #define D_NAMLEN(d) strlen((d)->d_name)
  69. #else    /* GNU C library.  */
  70. #define D_NAMLEN(d) ((d)->d_namlen)
  71. #endif    /* Not GNU C library.  */
  72. #else    /* Not POSIX or HAVE_DIRENT_H.  */
  73. #define direct dirent
  74. #define D_NAMLEN(d) ((d)->d_namlen)
  75. #ifdef    HAVE_SYS_NDIR_H
  76. #include <sys/ndir.h>
  77. #endif    /* HAVE_SYS_NDIR_H */
  78. #ifdef    HAVE_SYS_DIR_H
  79. #include <sys/dir.h>
  80. #endif    /* HAVE_SYS_DIR_H */
  81. #ifdef HAVE_NDIR_H
  82. #include <ndir.h>
  83. #endif    /* HAVE_NDIR_H */
  84. #endif    /* POSIX or HAVE_DIRENT_H or __GNU_LIBRARY__.  */
  85.  
  86. #if defined (POSIX) && !defined (__GNU_LIBRARY__)
  87. /* Posix does not require that the d_ino field be present, and some
  88.    systems do not provide it. */
  89. #define REAL_DIR_ENTRY(dp) 1
  90. #else
  91. #define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
  92. #endif /* POSIX */
  93.  
  94. #if    (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
  95. #include <stdlib.h>
  96. #include <string.h>
  97. #define    ANSI_STRING
  98. #else    /* No standard headers.  */
  99.  
  100. #ifdef HAVE_STRING_H
  101. #include <string.h>
  102. #define    ANSI_STRING
  103. #else
  104. #include <strings.h>
  105. #endif
  106. #ifdef    HAVE_MEMORY_H
  107. #include <memory.h>
  108. #endif
  109.  
  110. extern char *malloc (), *realloc ();
  111. extern void free ();
  112.  
  113. extern void qsort ();
  114. extern void abort (), exit ();
  115.  
  116. #endif    /* Standard headers.  */
  117.  
  118. #ifndef    ANSI_STRING
  119.  
  120. #ifndef    bzero
  121. extern void bzero ();
  122. #endif
  123. #ifndef    bcopy
  124. extern void bcopy ();
  125. #endif
  126.  
  127. #define    memcpy(d, s, n)    bcopy ((s), (d), (n))
  128. #define    strrchr    rindex
  129. /* memset is only used for zero here, but let's be paranoid.  */
  130. #define    memset(s, better_be_zero, n) \
  131.   ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
  132. #endif    /* Not ANSI_STRING.  */
  133.  
  134. #ifndef    HAVE_STRCOLL
  135. #define    strcoll    strcmp
  136. #endif
  137.  
  138.  
  139. #ifndef    __GNU_LIBRARY__
  140. #ifdef    __GNUC__
  141. __inline
  142. #endif
  143. static char *
  144. my_realloc (p, n)
  145.      char *p;
  146.      unsigned int n;
  147. {
  148.   /* These casts are the for sake of the broken Ultrix compiler,
  149.      which warns of illegal pointer combinations otherwise.  */
  150.   if (p == NULL)
  151.     return (char *) malloc (n);
  152.   return (char *) realloc (p, n);
  153. }
  154. #define    realloc    my_realloc
  155. #endif
  156.  
  157.  
  158. #if    !defined(__alloca) && !defined(__GNU_LIBRARY__)
  159.  
  160. #ifdef    __GNUC__
  161. #undef    alloca
  162. #define    alloca(n)    __builtin_alloca (n)
  163. #else    /* Not GCC.  */
  164. #if    defined (sparc) || defined (HAVE_ALLOCA_H)
  165. #include <alloca.h>
  166. #else    /* Not sparc or HAVE_ALLOCA_H.  */
  167. #ifndef    _AIX
  168. extern char *alloca ();
  169. #endif    /* Not _AIX.  */
  170. #endif    /* sparc or HAVE_ALLOCA_H.  */
  171. #endif    /* GCC.  */
  172.  
  173. #define    __alloca    alloca
  174.  
  175. #endif
  176.  
  177. #ifndef __GNU_LIBRARY__
  178. #define __lstat lstat
  179. #ifndef HAVE_LSTAT
  180. #define lstat stat
  181. #endif
  182. #ifdef STAT_MACROS_BROKEN
  183. #undef S_ISDIR
  184. #endif
  185. #ifndef S_ISDIR
  186. #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
  187. #endif
  188. #endif
  189.  
  190. #ifndef    STDC_HEADERS
  191. #undef    size_t
  192. #define    size_t    unsigned int
  193. #endif
  194.  
  195. /* Some system header files erroneously define these.
  196.    We want our own definitions from <fnmatch.h> to take precedence.  */
  197. #undef    FNM_PATHNAME
  198. #undef    FNM_NOESCAPE
  199. #undef    FNM_PERIOD
  200. #include <fnmatch.h>
  201.  
  202. /* Some system header files erroneously define these.
  203.    We want our own definitions from <glob.h> to take precedence.  */
  204. #undef    GLOB_ERR
  205. #undef    GLOB_MARK
  206. #undef    GLOB_NOSORT
  207. #undef    GLOB_DOOFFS
  208. #undef    GLOB_NOCHECK
  209. #undef    GLOB_APPEND
  210. #undef    GLOB_NOESCAPE
  211. #undef    GLOB_PERIOD
  212. #include <glob.h>
  213.  
  214. __ptr_t (*__glob_opendir_hook) __P ((const char *directory));
  215. const char *(*__glob_readdir_hook) __P ((__ptr_t stream));
  216. void (*__glob_closedir_hook) __P ((__ptr_t stream));
  217.  
  218. static int glob_pattern_p __P ((const char *pattern, int quote));
  219. static int glob_in_dir __P ((const char *pattern, const char *directory,
  220.                  int flags,
  221.                  int (*errfunc) __P ((const char *, int)),
  222.                  glob_t *pglob));
  223. static int prefix_array __P ((const char *prefix, char **array, size_t n));
  224. static int collated_compare __P ((const __ptr_t, const __ptr_t));
  225.  
  226. /* Do glob searching for PATTERN, placing results in PGLOB.
  227.    The bits defined above may be set in FLAGS.
  228.    If a directory cannot be opened or read and ERRFUNC is not nil,
  229.    it is called with the pathname that caused the error, and the
  230.    `errno' value from the failing call; if it returns non-zero
  231.    `glob' returns GLOB_ABEND; if it returns zero, the error is ignored.
  232.    If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
  233.    Otherwise, `glob' returns zero.  */
  234. int
  235. glob (pattern, flags, errfunc, pglob)
  236.      const char *pattern;
  237.      int flags;
  238.      int (*errfunc) __P ((const char *, int));
  239.      glob_t *pglob;
  240. {
  241.   const char *filename;
  242.   char *dirname;
  243.   size_t dirlen;
  244.   int status;
  245.   int oldcount;
  246.  
  247.   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
  248.     {
  249.       errno = EINVAL;
  250.       return -1;
  251.     }
  252.  
  253.   /* Find the filename.  */
  254.   filename = strrchr (pattern, '/');
  255.   if (filename == NULL)
  256.     {
  257.       filename = pattern;
  258.       dirname = (char *) ".";
  259.       dirlen = 0;
  260.     }
  261.   else if (filename == pattern)
  262.     {
  263.       /* "/pattern".  */
  264.       dirname = (char *) "/";
  265.       dirlen = 1;
  266.       ++filename;
  267.     }
  268.   else
  269.     {
  270.       dirlen = filename - pattern;
  271.       dirname = (char *) __alloca (dirlen + 1);
  272.       memcpy (dirname, pattern, dirlen);
  273.       dirname[dirlen] = '\0';
  274.       ++filename;
  275.     }
  276.  
  277.   if (filename[0] == '\0' && dirlen > 1)
  278.     /* "pattern/".  Expand "pattern", appending slashes.  */
  279.     {
  280.       int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
  281.       if (val == 0)
  282.     pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK);
  283.       return val;
  284.     }
  285.  
  286.   if (!(flags & GLOB_APPEND))
  287.     {
  288.       pglob->gl_pathc = 0;
  289.       pglob->gl_pathv = NULL;
  290.     }
  291.  
  292.   oldcount = pglob->gl_pathc;
  293.  
  294.   if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
  295.     {
  296.       /* The directory name contains metacharacters, so we
  297.      have to glob for the directory, and then glob for
  298.      the pattern in each directory found.  */
  299.       glob_t dirs;
  300.       register int i;
  301.  
  302.       status = glob (dirname,
  303.              ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) |
  304.               GLOB_NOSORT),
  305.              errfunc, &dirs);
  306.       if (status != 0)
  307.     return status;
  308.  
  309.       /* We have successfully globbed the preceding directory name.
  310.      For each name we found, call glob_in_dir on it and FILENAME,
  311.      appending the results to PGLOB.  */
  312.       for (i = 0; i < dirs.gl_pathc; ++i)
  313.     {
  314.       int oldcount;
  315.  
  316. #ifdef    SHELL
  317.       {
  318.         /* Make globbing interruptible in the bash shell. */
  319.         extern int interrupt_state;
  320.  
  321.         if (interrupt_state)
  322.           {
  323.         globfree (&dirs);
  324.         globfree (&files);
  325.         return GLOB_ABEND;
  326.           }
  327.       }
  328. #endif /* SHELL.  */
  329.  
  330.       oldcount = pglob->gl_pathc;
  331.       status = glob_in_dir (filename, dirs.gl_pathv[i],
  332.                 (flags | GLOB_APPEND) & ~GLOB_NOCHECK,
  333.                 errfunc, pglob);
  334.       if (status == GLOB_NOMATCH)
  335.         /* No matches in this directory.  Try the next.  */
  336.         continue;
  337.  
  338.       if (status != 0)
  339.         {
  340.           globfree (&dirs);
  341.           globfree (pglob);
  342.           return status;
  343.         }
  344.  
  345.       /* Stick the directory on the front of each name.  */
  346.       if (prefix_array (dirs.gl_pathv[i],
  347.                 &pglob->gl_pathv[oldcount],
  348.                 pglob->gl_pathc - oldcount))
  349.         {
  350.           globfree (&dirs);
  351.           globfree (pglob);
  352.           return GLOB_NOSPACE;
  353.         }
  354.     }
  355.  
  356.       flags |= GLOB_MAGCHAR;
  357.  
  358.       if (pglob->gl_pathc == oldcount)
  359.     /* No matches.  */
  360.     if (flags & GLOB_NOCHECK)
  361.       {
  362.         size_t len = strlen (pattern) + 1;
  363.         char *patcopy = (char *) malloc (len);
  364.         if (patcopy == NULL)
  365.           return GLOB_NOSPACE;
  366.         memcpy (patcopy, pattern, len);
  367.  
  368.         pglob->gl_pathv
  369.           = (char **) realloc (pglob->gl_pathv,
  370.                    (pglob->gl_pathc +
  371.                     ((flags & GLOB_DOOFFS) ?
  372.                      pglob->gl_offs : 0) +
  373.                     1 + 1) *
  374.                    sizeof (char *));
  375.         if (pglob->gl_pathv == NULL)
  376.           {
  377.         free (patcopy);
  378.         return GLOB_NOSPACE;
  379.           }
  380.  
  381.         if (flags & GLOB_DOOFFS)
  382.           while (pglob->gl_pathc < pglob->gl_offs)
  383.         pglob->gl_pathv[pglob->gl_pathc++] = NULL;
  384.  
  385.         pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
  386.         pglob->gl_pathv[pglob->gl_pathc] = NULL;
  387.         pglob->gl_flags = flags;
  388.       }
  389.     else
  390.       return GLOB_NOMATCH;
  391.     }
  392.   else
  393.     {
  394.       status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
  395.       if (status != 0)
  396.     return status;
  397.  
  398.       if (dirlen > 0)
  399.     {
  400.       /* Stick the directory on the front of each name.  */
  401.       if (prefix_array (dirname,
  402.                 &pglob->gl_pathv[oldcount],
  403.                 pglob->gl_pathc - oldcount))
  404.         {
  405.           globfree (pglob);
  406.           return GLOB_NOSPACE;
  407.         }
  408.     }
  409.     }
  410.  
  411.   if (flags & GLOB_MARK)
  412.     {
  413.       /* Append slashes to directory names.  glob_in_dir has already
  414.      allocated the extra character for us.  */
  415.       int i;
  416.       struct stat st;
  417.       for (i = oldcount; i < pglob->gl_pathc; ++i)
  418.     if (__lstat (pglob->gl_pathv[i], &st) == 0 &&
  419.         S_ISDIR (st.st_mode))
  420.       strcat (pglob->gl_pathv[i], "/");
  421.     }
  422.  
  423.   if (!(flags & GLOB_NOSORT))
  424.     /* Sort the vector.  */
  425.     qsort ((__ptr_t) &pglob->gl_pathv[oldcount],
  426.        pglob->gl_pathc - oldcount,
  427.        sizeof (char *), collated_compare);
  428.  
  429.   return 0;
  430. }
  431.  
  432.  
  433. /* Free storage allocated in PGLOB by a previous `glob' call.  */
  434. void
  435. globfree (pglob)
  436.      register glob_t *pglob;
  437. {
  438.   if (pglob->gl_pathv != NULL)
  439.     {
  440.       register int i;
  441.       for (i = 0; i < pglob->gl_pathc; ++i)
  442.     if (pglob->gl_pathv[i] != NULL)
  443.       free ((__ptr_t) pglob->gl_pathv[i]);
  444.       free ((__ptr_t) pglob->gl_pathv);
  445.     }
  446. }
  447.  
  448.  
  449. /* Do a collated comparison of A and B.  */
  450. static int
  451. collated_compare (a, b)
  452.      const __ptr_t a;
  453.      const __ptr_t b;
  454. {
  455.   const char *const s1 = *(const char *const * const) a;
  456.   const char *const s2 = *(const char *const * const) b;
  457.  
  458.   if (s1 == s2)
  459.     return 0;
  460.   if (s1 == NULL)
  461.     return 1;
  462.   if (s2 == NULL)
  463.     return -1;
  464.   return strcoll (s1, s2);
  465. }
  466.  
  467.  
  468. /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
  469.    elements in place.  Return nonzero if out of memory, zero if successful.
  470.    A slash is inserted between DIRNAME and each elt of ARRAY,
  471.    unless DIRNAME is just "/".  Each old element of ARRAY is freed.  */
  472. static int
  473. prefix_array (dirname, array, n)
  474.      const char *dirname;
  475.      char **array;
  476.      size_t n;
  477. {
  478.   register size_t i;
  479.   size_t dirlen = strlen (dirname);
  480.  
  481.   if (dirlen == 1 && dirname[0] == '/')
  482.     /* DIRNAME is just "/", so normal prepending would get us "//foo".
  483.        We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
  484.     dirlen = 0;
  485.  
  486.   for (i = 0; i < n; ++i)
  487.     {
  488.       size_t eltlen = strlen (array[i]) + 1;
  489.       char *new = (char *) malloc (dirlen + 1 + eltlen);
  490.       if (new == NULL)
  491.     {
  492.       while (i > 0)
  493.         free ((__ptr_t) array[--i]);
  494.       return 1;
  495.     }
  496.  
  497.       memcpy (new, dirname, dirlen);
  498.       new[dirlen] = '/';
  499.       memcpy (&new[dirlen + 1], array[i], eltlen);
  500.       free ((__ptr_t) array[i]);
  501.       array[i] = new;
  502.     }
  503.  
  504.   return 0;
  505. }
  506.  
  507.  
  508. /* Return nonzero if PATTERN contains any metacharacters.
  509.    Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
  510. static int
  511. glob_pattern_p (pattern, quote)
  512.      const char *pattern;
  513.      int quote;
  514. {
  515.   register const char *p;
  516.   int open = 0;
  517.  
  518.   for (p = pattern; *p != '\0'; ++p)
  519.     switch (*p)
  520.       {
  521.       case '?':
  522.       case '*':
  523.     return 1;
  524.  
  525.       case '\\':
  526.     if (quote)
  527.       ++p;
  528.     break;
  529.  
  530.       case '[':
  531.     open = 1;
  532.     break;
  533.  
  534.       case ']':
  535.     if (open)
  536.       return 1;
  537.     break;
  538.       }
  539.  
  540.   return 0;
  541. }
  542.  
  543.  
  544. /* Like `glob', but PATTERN is a final pathname component,
  545.    and matches are searched for in DIRECTORY.
  546.    The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
  547.    The GLOB_APPEND flag is assumed to be set (always appends).  */
  548. static int
  549. glob_in_dir (pattern, directory, flags, errfunc, pglob)
  550.      const char *pattern;
  551.      const char *directory;
  552.      int flags;
  553.      int (*errfunc) __P ((const char *, int));
  554.      glob_t *pglob;
  555. {
  556.   __ptr_t stream;
  557.  
  558.   struct globlink
  559.     {
  560.       struct globlink *next;
  561.       char *name;
  562.     };
  563.   struct globlink *names = NULL;
  564.   size_t nfound = 0;
  565.  
  566.   if (!glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
  567.     {
  568.       stream = NULL;
  569.       flags |= GLOB_NOCHECK;
  570.     }
  571.   else
  572.     {
  573.       flags |= GLOB_MAGCHAR;
  574.  
  575.       stream = (__glob_opendir_hook ? (*__glob_opendir_hook) (directory)
  576.         : (__ptr_t) opendir (directory));
  577.       if (stream == NULL)
  578.     {
  579.       if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
  580.           (flags & GLOB_ERR))
  581.         return GLOB_ABEND;
  582.     }
  583.       else
  584.     while (1)
  585.       {
  586.         const char *name;
  587.         size_t len;
  588.  
  589.         if (__glob_readdir_hook)
  590.           {
  591.         name = (*__glob_readdir_hook) (stream);
  592.         if (name == NULL)
  593.           break;
  594.         len = 0;
  595.           }
  596.         else
  597.           {
  598.         struct dirent *d = readdir ((DIR *) stream);
  599.         if (d == NULL)
  600.           break;
  601.         if (! REAL_DIR_ENTRY (d))
  602.           continue;
  603.         name = d->d_name;
  604. #ifdef    HAVE_D_NAMLEN
  605.         len = d->d_namlen;
  606. #else
  607.         len = 0;
  608. #endif
  609.           }
  610.         
  611.         if (fnmatch (pattern, name,
  612.              (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
  613.              ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)) == 0)
  614.           {
  615.         struct globlink *new
  616.           = (struct globlink *) __alloca (sizeof (struct globlink));
  617.         if (len == 0)
  618.           len = strlen (name);
  619.         new->name
  620.           = (char *) malloc (len + ((flags & GLOB_MARK) ? 1 : 0) + 1);
  621.         if (new->name == NULL)
  622.           goto memory_error;
  623.         memcpy ((__ptr_t) new->name, name, len);
  624.         new->name[len] = '\0';
  625.         new->next = names;
  626.         names = new;
  627.         ++nfound;
  628.           }
  629.       }
  630.     }
  631.  
  632.   if (nfound == 0 && (flags & GLOB_NOCHECK))
  633.     {
  634.       size_t len = strlen (pattern);
  635.       nfound = 1;
  636.       names = (struct globlink *) __alloca (sizeof (struct globlink));
  637.       names->next = NULL;
  638.       names->name = (char *) malloc (len + 1);
  639.       if (names->name == NULL)
  640.     goto memory_error;
  641.       memcpy (names->name, pattern, len);
  642.       names->name[len] = '\0';
  643.     }
  644.  
  645.   pglob->gl_pathv
  646.     = (char **) realloc (pglob->gl_pathv,
  647.              (pglob->gl_pathc +
  648.               ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
  649.               nfound + 1) *
  650.              sizeof (char *));
  651.   if (pglob->gl_pathv == NULL)
  652.     goto memory_error;
  653.  
  654.   if (flags & GLOB_DOOFFS)
  655.     while (pglob->gl_pathc < pglob->gl_offs)
  656.       pglob->gl_pathv[pglob->gl_pathc++] = NULL;
  657.  
  658.   for (; names != NULL; names = names->next)
  659.     pglob->gl_pathv[pglob->gl_pathc++] = names->name;
  660.   pglob->gl_pathv[pglob->gl_pathc] = NULL;
  661.  
  662.   pglob->gl_flags = flags;
  663.  
  664.   if (stream != NULL)
  665.     {
  666.       int save = errno;
  667.       if (__glob_closedir_hook)
  668.     (*__glob_closedir_hook) (stream);
  669.       else
  670.     (void) closedir ((DIR *) stream);
  671.       errno = save;
  672.     }
  673.   return nfound == 0 ? GLOB_NOMATCH : 0;
  674.  
  675.  memory_error:
  676.   {
  677.     int save = errno;
  678.     if (__glob_closedir_hook)
  679.       (*__glob_closedir_hook) (stream);
  680.     else
  681.       (void) closedir ((DIR *) stream);
  682.     errno = save;
  683.   }
  684.   while (names != NULL)
  685.     {
  686.       if (names->name != NULL)
  687.     free ((__ptr_t) names->name);
  688.       names = names->next;
  689.     }
  690.   return GLOB_NOSPACE;
  691. }
  692.  
  693. #endif    /* _LIBC or not __GNU_LIBRARY__.  */
  694.